package fr.insee.solr.service.state;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.beanutils.NestedNullException;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;

import fr.insee.solr.model.annotation.SolrField;
import fr.insee.solr.service.impl.SolrInseeException;
import fr.insee.solr.utils.ReflectUtils;

public class StateNestedMultivalued implements IState {

	@Override
	public Object getValue(Field f, SolrField a, Object o) throws SolrInseeException {
		List<Object> liste = new ArrayList<>();

		String listeName = f.getName();
		String beanName = StringUtils.substring(a.beanName(), listeName.length() + 1);
		try {
			Object iterable = PropertyUtils.getProperty(o, listeName);
			if (iterable instanceof Iterable<?>) {
				for (Object v : (Iterable<?>) iterable) {
					Object n = PropertyUtils.getProperty(v, beanName);
					if (n != null) {
						liste.add(n);
					}
				}
				if (liste.isEmpty())
					liste = null;

				return liste;
			}
			else
				throw new SolrInseeException(ERROR_NO_ITERABLE_TYPE + a.fieldName());
		}
		catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
			throw new SolrInseeException(ERROR_NO_SUCH_FIELD + a.fieldName(), e);
		}
		catch (NestedNullException e) {
			return null;
		}
	}

	@Override
	public void fillValue(Object bean, Field f, SolrField a, Object solrValue) throws SolrInseeException {
		try {
			String listeName = f.getName();
			String beanName = StringUtils.substring(a.beanName(), listeName.length() + 1);

			Class<?> typeListe = PropertyUtils.getPropertyType(bean, listeName);
			Collection<Object> collection = StateUtils.createCollection(typeListe);

			if (solrValue != null && solrValue instanceof Collection) {
				ParameterizedType listeType = (ParameterizedType) f.getGenericType();
				Class<?> classGeneric = (Class<?>) listeType.getActualTypeArguments()[0];
				for (Object o : ((Collection<?>) solrValue)) {
					Object value = classGeneric.newInstance();

					ReflectUtils.instanciateAttributs(beanName, value);
					PropertyUtils.setProperty(value, beanName, o);
					collection.add(value);
				}
			}
			if (collection != null)
				PropertyUtils.setProperty(bean, listeName, collection);
		}
		catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | InstantiationException e) {
			throw new SolrInseeException(ERROR_FILL_FIELD + f.getName(), e);
		}

	}

}
